package main

import (
	"fmt"
	"log"
	"strconv"

	"github.com/streadway/amqp"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
		panic(fmt.Sprintf("%s: %s", msg, err))
	}
}

func fib(n int) int {
	if n== 0 {
		return 0
	}else if n==1 {
		return 1
	}else {
		return fib(n-1) + fib(n-2)
	}
}

func main(){
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	failOnError(err, "Failed to connect to RabbitMQ")
	defer conn.Close()

	ch, err := conn.Channel()
	failOnError(err, "Failed to open a channel")
	defer ch.Close()

	q, err := ch.QueueDeclare(
		"rpc_queue",     //name
		false,            //durables
		false,            //delete when unused
		false,            //exclusive
		false,            //no wait
		nil,            //args
	)
	failOnError(err, "Failed to declare a queue")

	err = ch.Qos(
		1,     // prefetch count
		0,  // prefetch size
		false,    //global
	)
	failOnError(err, "Failed to set Qos")

	msgs, err := ch.Consume(
		q.Name,        //queue
		"",            //exchange
		false,        // auto-ack
		false,        //exclusive
		false,        //no-local
		false,        //no-wait
		nil,        //args
	)
	failOnError(err, "Failed to register a consumer")

	forever := make(chan bool)

	go func() {
		for d := range msgs {
			n, err := strconv.Atoi(string(d.Body))
			failOnError(err, "Failed to convert body to an integer")

			log.Printf(" [.] fib(%d)", n)
			response := fib(n)

			err = ch.Publish(
				"",        //exchange
				d.ReplyTo,        //routing key
				false,        //mandatory
				false,        //immediate
				amqp.Publishing{
					ContentType :    "text/plain",
					CorrelationId:    d.CorrelationId,
					Body:            []byte(strconv.Itoa(response)),
				})
			failOnError(err, "Failed to publish a message")

			d.Ack(false)
		}
	}()

	log.Printf(" [*] Awaiting RPC reqeusts")
	<-forever
}